package com.itheima.reggie.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.domain.Category;
import com.itheima.reggie.domain.Dish;
import com.itheima.reggie.domain.DishFlavor;
import com.itheima.reggie.mapper.CategoryMapper;
import com.itheima.reggie.mapper.DishFlavorMapper;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service    //将service层交给ioc容器管理
@Transactional      //事务管理器
@Slf4j      //日志类
public class DishServiceImpl implements DishService {

    //依赖注入mapper层
    @Autowired
    private CategoryMapper categoryMapper;

    //依赖注入mapper层
    @Autowired
    private DishMapper dishMapper;


    //依赖注入mapper层
    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    //依赖注入redis父工具类
    @Autowired
    private RedisTemplate redisTemplate;


    //分页查询 + 模糊查询
    @Override
    public Page<Dish> findByPage(Integer pageNum, Integer pageSize, String name) {
        //1. 业务处理
        //1-1 创建条件构造器
        LambdaQueryWrapper<Dish> qw = new LambdaQueryWrapper<>();
        //1-2 设置条件
        qw.like(StrUtil.isNotBlank(name), Dish::getName, name);   //设置模糊查询
        qw.orderByAsc(Dish::getSort);       //设置正序
        //1-3 开启分页
        Page<Dish> page = new Page<>(pageNum, pageSize);
        //1-4 调用mp查询
        page = dishMapper.selectPage(page, qw);

        //2.遍历菜品信息
        List<Dish> dishList = page.getRecords();
        for (Dish dish : dishList) {
            //根据categoryId查询口味列表
            //2-1 调用mappper查询
            List<DishFlavor> dishFlavorList = dishFlavorMapper.selectList(new LambdaQueryWrapper<DishFlavor>().eq(DishFlavor::getDishId, dish.getId()));
            //2-2 将口味封装到Dish中
            dish.setFlavors(dishFlavorList);
            //2-3 根据categoryId查询菜品口味
            Category category = categoryMapper.selectById(dish.getCategoryId());
            //2-4 将菜品分类信息封装到Dish中
            dish.setCategoryName(category.getName());
        }

        //3. 返回页面
        return page;
    }

    //回显菜品分类信息
    @Override
    public List<Category> findByType(Integer type) {
        //业务处理
        //1. 创建条件构造器
        LambdaQueryWrapper<Category> qw = new LambdaQueryWrapper<>();
        //2. 设置条件
        qw.eq(Category::getType, type);
        //3. 调用mp查询菜品分类信息
        return categoryMapper.selectList(qw);
    }

    //新增菜品信息
    @Override
    public void addDish(Dish dish) {
        //业务处理
        //1. 调用mp存入dish表
        dishMapper.insert(dish);
        //2. 将口味关联到dish_flavor表
        //2. 遍历
        for (DishFlavor flavor : dish.getFlavors()) {
            //关联菜品id
            flavor.setDishId(dish.getId());
            //新增口味
            dishFlavorMapper.insert(flavor);
        }

        //新增后,清除redis
        redisTemplate.delete("dish:"+ dish.getCategoryId());
    }

    //回显菜品
    @Override
    public Dish findById(Long id) {
        //业务逻辑
        //1. 根据id查询dish表
        Dish dish = dishMapper.selectById(id);

        //前端写好的
        /*//查询category表中的名字
        Category category = categoryMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getId, dish.getCategoryId()));
        //封装到dish中
        dish.setCategoryName(category.getName());*/

        //2. 根据id查询flavor表
        List<DishFlavor> dishFlavorList = dishFlavorMapper.selectList(new LambdaQueryWrapper<DishFlavor>().eq(DishFlavor::getDishId, id));
        //3. 将口味flavor封装到dish中
        dish.setFlavors(dishFlavorList);
        //4.返回
        return dish;
    }

    //修改菜品
    @Override
    public void updateById(Dish dish) {
        //业务逻辑
        //1.修改菜品原有信息
        dishMapper.updateById(dish);
        //2.删除原有口味信息
        //根据dish的id删除口味表中的数据
        dishFlavorMapper.delete(new LambdaQueryWrapper<DishFlavor>().eq(DishFlavor::getDishId, dish.getId()));
        //3.新增口味信息
        //遍历口味列表
        for (DishFlavor flavor : dish.getFlavors()) {
            //将口味表的dishId与dish关联
            flavor.setDishId(dish.getId());
            //新增口味
            dishFlavorMapper.insert(flavor);
        }

        //修改后,清除全部缓存
        //i.模糊查询所有key
        Set allKeys = redisTemplate.keys("dish:*");
        //ii.批量删除
        redisTemplate.delete(allKeys);
    }

    //(批量)禁售/启用
    @Override
    public void updateStatus(Integer status, List<Long> ids) {
        //业务处理
        //1.根据id查询dish列表
        List<Dish> dishList = dishMapper.selectBatchIds(ids);
        //2.设置status
        //遍历
        for (Dish dish : dishList) {
            //修改装填
            dish.setStatus(status);
            //3.根据id更新dish列表
            dishMapper.updateById(dish);
        }

        //修改后,清除全部缓存
        //i.模糊查询所有key
        Set allKeys = redisTemplate.keys("dish:*");
        //ii.批量删除
        redisTemplate.delete(allKeys);

        /*
        //1. 创建dish对象
        Dish dish = new Dish();
        //2. 修改状态
        dish.setStatus(status);
        //3. 根据id更新dish列表
        dishMapper.update(dish,new LambdaQueryWrapper<Dish>().in(Dish::getId,ids));
         */

    }

    //(批量)删除
    @Override
    public void deleteByIds(List<Long> ids) {
        /*//方法一:
        //业务逻辑
        //1. 判断商品是否在起售状态
        //1-1 根据ids查询dish列表
        List<Dish> dishList = dishMapper.selectBatchIds(ids);
        //1-2 遍历
        for (Dish dish : dishList) {
            //2. 若起售,则无法删除,抛出异常
            if (dish.getStatus() == 1) {
                throw new CustomException("无法删除:此菜品在起售状态...");
            }
        }
        //3. 若禁售,则可删除
        //3-1 根据id删除dish表
        dishMapper.deleteBatchIds(ids);
        //3-2 根据id删除dishFlavor表
        dishFlavorMapper.delete(new LambdaQueryWrapper<DishFlavor>().in(DishFlavor::getDishId, ids));
*/
        //方法二:
        //1. 创建条件构造器
        LambdaQueryWrapper<Dish> qw = new LambdaQueryWrapper<>();
        //2. 设置条件
        qw.in(Dish::getId, ids); // id in (ids)
        qw.eq(Dish::getStatus, 1);       //status = 1
        //3. 调用mp查询总数,判断
        if (dishMapper.selectCount(qw) > 0) {
            //若不为0,则无法删除,抛出异常
            throw new CustomException("无法删除:此菜品在起售状态...");
        }
        //4.若为0,则删除
        //4-1 删除dish表
        dishMapper.deleteBatchIds(ids);
        //4-2 删除dishFlavor表
        dishFlavorMapper.delete(new LambdaQueryWrapper<DishFlavor>().in(DishFlavor::getDishId, ids));

        //修改后,清除全部缓存
        //i.模糊查询所有key
        Set allKeys = redisTemplate.keys("dish:*");
        //ii.批量删除
        redisTemplate.delete(allKeys);
    }

     //c端查询菜品列表
     @Override
     public List<Dish> findList(String categoryId, Integer status) {
         //声明返回的List
         List<Dish> dishList = null;

         //定义菜品分类的key
         String dishKey = "dish:" + categoryId;


         //判断是否在redis内部
         if (redisTemplate.hasKey(dishKey)) {
             log.info("查询redis..");
             //若存在则取出并返回
             dishList = (List<Dish>) redisTemplate.opsForValue().get(dishKey);
         }else {
             log.info("查询MySQL");
             //不存在,则存入
             //业务处理
             //1.创建条件
             LambdaQueryWrapper<Dish> qw = new LambdaQueryWrapper<>();
             qw.eq(Dish::getCategoryId,categoryId);
             qw.eq(Dish::getStatus,status);
             //2.调用mapper查询Dish表
             dishList = dishMapper.selectList(qw);
             //3.遍历查询口味
             for (Dish dish : dishList) {
                 //根据dishId查询dishFlavor表
                 List<DishFlavor> flavorList = dishFlavorMapper.selectList(new LambdaQueryWrapper<DishFlavor>().eq(DishFlavor::getDishId, dish.getId()));
                 //将口味信息存到dish中
                 dish.setFlavors(flavorList);
             }

             //同步到redis中
             redisTemplate.opsForValue().set(dishKey,dishList);
         }

         //4.返回菜品列表
         return dishList;
     }

}
